package com.airlines.crewassignment.service.crew.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.airlines.common.AgeUtil;
import com.airlines.common.BeanFiledUtils;
import com.airlines.common.Page;
import com.airlines.common.StringToListUtil;
import com.airlines.common.TraceUtil;
import com.airlines.crewassignment.constant.RuleConstant;
import com.airlines.crewassignment.constant.TechConstant;
import com.airlines.crewassignment.dao.AirPortMapper;
import com.airlines.crewassignment.dao.CrewMapper;
import com.airlines.crewassignment.dao.CrewTaskMapper;
import com.airlines.crewassignment.dao.FlightInfoMapper;
import com.airlines.crewassignment.domain.Airport;
import com.airlines.crewassignment.domain.Crew;
import com.airlines.crewassignment.domain.CrewFlightExperience;
import com.airlines.crewassignment.domain.CrewFlightExperienceAcType;
import com.airlines.crewassignment.domain.CrewTask;
import com.airlines.crewassignment.domain.DateTimeRange;
import com.airlines.crewassignment.domain.FlightInfo;
import com.airlines.crewassignment.domain.LinkLine;
import com.airlines.crewassignment.domain.Skill;
import com.airlines.crewassignment.domain.Tech;
import com.airlines.crewassignment.domain.crew.CrewExamine;
import com.airlines.crewassignment.domain.crew.CrewRestDateTime;
import com.airlines.crewassignment.entity.crew.CrewConflictOther;
import com.airlines.crewassignment.entity.crew.CrewInfoForAssign;
import com.airlines.crewassignment.service.crew.CrewConflictService;
import com.airlines.crewassignment.service.crew.CrewExamineService;
import com.airlines.crewassignment.service.crew.CrewFlightExperienceAcTypeService;
import com.airlines.crewassignment.service.crew.CrewFlightExperienceService;
import com.airlines.crewassignment.service.crew.CrewRankConvertService;
import com.airlines.crewassignment.service.crew.CrewRestDateTimeService;
import com.airlines.crewassignment.service.crew.CrewService;
import com.airlines.crewassignment.service.crew.CrewTaskService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

/**
 * @author xxxx
 * @date 2018年3月26日
 * @description
 */
@Service
public class CrewServiceImpl implements CrewService {
	static Log log = LogFactory.getLog(CrewServiceImpl.class);

	@Autowired
	private CrewMapper crewMapper;
	@Autowired
	private AirPortMapper airPortMapper;
	@Autowired
	private FlightInfoMapper flightInfoMapper;

	@Autowired
	private CrewFlightExperienceService crewFlightExperienceService;
	@Autowired
	private CrewFlightExperienceAcTypeService crewFlightExperienceAcTypeService;
	@Autowired
	private CrewRankConvertService crewRankConvertService;
	@Autowired
	private CrewRestDateTimeService crewRestDateTimeService;
	@Autowired
	private CrewConflictService crewConflictService;
	@Autowired
	private CrewTaskService crewTaskService;
	@Autowired
	private CrewTaskMapper crewTaskMapper;
	@Autowired
	private CrewExamineService crewExamineService;

	@Override
	public List<Crew> listCrewBase(String dutyCode) {
		List<Crew> crewList = crewMapper.listCrewBase(dutyCode, null);
		// 计算年龄
		for (Crew c : crewList) {
			Date birthday = c.getBirthday();
			int age = AgeUtil.getAgeFromBirthTime(birthday);
			c.setAge(age);
		}

		return crewList;
	}

	@Override
	public List<Crew> listCrewBase(String dutyCode, String workcode) {
		List<Crew> crewList = crewMapper.listCrewBase(dutyCode, workcode);
		// 计算年龄
		for (Crew c : crewList) {
			Date birthday = c.getBirthday();
			int age = AgeUtil.getAgeFromBirthTime(birthday);
			c.setAge(age);
		}

		return crewList;
	}

	@Override
	public List<Crew> listStaff(Map<String, String> parameters) {
		return crewMapper.listStaff(parameters);
	}

	@Override
	public List<Crew> listStaffPcode(Map<String, String> parameters) {
		return crewMapper.listStaffPcode(parameters);
	}

	@Override
	public List<Crew> staffInfo(String workcode) {
		return (List<Crew>) crewMapper.staffInfo(workcode);

	}

	@Override
	public List<Crew> listCrewAllInfo(String dutyCode, Date beforeFlightDate, Date endFlightDate) {
		// 基本信息查询
		List<Crew> crewList = this.listCrewBase(dutyCode);

		// 各种指标初始化开始
		this.techEListInit(crewList, dutyCode, beforeFlightDate);
		this.techIListInit(crewList, dutyCode, beforeFlightDate);
		this.techZListInit(crewList, dutyCode, beforeFlightDate);
		this.skillInit(crewList, dutyCode, beforeFlightDate);
		this.crewFlightExperienceInit(crewList, dutyCode, beforeFlightDate, endFlightDate);
		this.lastAirportInit(crewList, dutyCode, beforeFlightDate);
		this.flightDurationLimitOfMonthInit(crewList, dutyCode, beforeFlightDate);

		crewFlightExperienceService.flightInfoListYearInit(crewList, dutyCode, beforeFlightDate);

		this.flightDurationLastYearInit(crewList, dutyCode, beforeFlightDate);
		this.flightDurationLastMonthInit(crewList, dutyCode, beforeFlightDate);

		this.dutyDurationLastYearInit(crewList, dutyCode, beforeFlightDate);
		this.dutyDurationLastMonthInit(crewList, dutyCode, beforeFlightDate);
		this.dutyDurationListInit(crewList, dutyCode, beforeFlightDate);

		this.nightPassCountLastYearInit(crewList, dutyCode, beforeFlightDate);
		this.nightPassCountLastMonthInit(crewList, dutyCode, beforeFlightDate);

		this.flightMoreThanCountLastYearInit(crewList, dutyCode, beforeFlightDate);
		this.flightMoreThanCountLastMonthInit(crewList, dutyCode, beforeFlightDate);

		this.nightFlyCountLastYearInit(crewList, dutyCode, beforeFlightDate);
		this.nightFlyCountLastMonthInit(crewList, dutyCode, beforeFlightDate);

		this.badFlightCountLastYearInit(crewList, dutyCode, beforeFlightDate);
		this.badFlightCountLastMonthInit(crewList, dutyCode, beforeFlightDate);

		this.lastVacationAndStopFlyInit(crewList, dutyCode, beforeFlightDate);
		this.lastSickLeaveInit(crewList, dutyCode, beforeFlightDate);

		this.cfeAcTypeListInit(crewList, dutyCode, beforeFlightDate, endFlightDate);
		this.crewRestDateTimeListInit(crewList, dutyCode, beforeFlightDate);
		this.crewConflictOtherInit(crewList, dutyCode, beforeFlightDate);
		this.crewTaskListBetweenFlightDateInit(crewList, dutyCode, beforeFlightDate, endFlightDate);
		this.crewExamineListInit(crewList, dutyCode, beforeFlightDate);
		this.lastLinkLine(crewList, dutyCode, beforeFlightDate);
		this.airPortsSetLastSixMonthInit(crewList, dutyCode, beforeFlightDate);
		this.seatDurationAllInit(crewList, dutyCode, beforeFlightDate);

		// 指标排名初始化
		crewRankConvertService.convert(crewList, "flightDurationLastYear");
		crewRankConvertService.convert(crewList, "flightDurationLastMonth");

		crewRankConvertService.convert(crewList, "nightPassCountLastYear");
		crewRankConvertService.convert(crewList, "nightPassCountLastMonth");

		crewRankConvertService.convert(crewList, "dutyDurationLastYear");
		crewRankConvertService.convert(crewList, "dutyDurationLastMonth");

		crewRankConvertService.convert(crewList, "flightMoreThanCountLastYear");
		crewRankConvertService.convert(crewList, "flightMoreThanCountLastMonth");

		crewRankConvertService.convert(crewList, "nightFlyCountLastYear");
		crewRankConvertService.convert(crewList, "nightFlyCountLastMonth");

		crewRankConvertService.convert(crewList, "badFlightCountLastYear");
		crewRankConvertService.convert(crewList, "badFlightCountLastMonth");

		crewRankConvertService.convert(crewList, "lastVacationAndStopFly");
		crewRankConvertService.convert(crewList, "seatDurationAll");

		return crewList;
	}

	@Override
	public List<Crew> listCrewAllInfoForVo(String dutyCode, Date beforeFlightDate, Date endFlightDate) {
		// 基本信息查询
		List<Crew> crewList = this.listCrewBase(dutyCode);

		// 各种指标初始化开始

		this.techZListInit(crewList, dutyCode, beforeFlightDate);
		this.skillInit(crewList, dutyCode, beforeFlightDate);
		this.crewFlightExperienceInit(crewList, dutyCode, beforeFlightDate, endFlightDate);
		this.lastAirportInit(crewList, dutyCode, beforeFlightDate);

		this.flightDurationLastYearInit(crewList, dutyCode, beforeFlightDate);
		this.flightDurationLastMonthInit(crewList, dutyCode, beforeFlightDate);

		this.dutyDurationLastMonthInit(crewList, dutyCode, beforeFlightDate);
		this.dutyDurationLastWeekInit(crewList, dutyCode, beforeFlightDate);

		return crewList;
	}

	// @Override
	// public List<Crew> listCrewByLinkLine(List<LinkLine> linkLines) {
	// List<Crew> allCrews = this.listCrewAllInfo("F",null,null);
	// List<Crew> crews = linkLines.stream()
	// .flatMap(l -> l.getPositionList().stream())
	// .map(p -> {
	// Optional<Crew> crew = allCrews.stream()
	// .filter(c -> c.getWorkcode().equals(p.getWorkcode()))
	// .findFirst();
	// return crew.get();
	// })
	// .collect(Collectors.toList());
	// return crews;
	// }

	/**
	 * 机组 公司授权初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void techIListInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		Tech techQuery =  new Tech();
		techQuery.setDutyCode(dutyCode);
		List<Tech> techList = crewMapper.listCrewTech(techQuery);
		this.techMatch(techList, TechConstant.INEX_I, crewList);
	}

	/**
	 * 机组局方授权初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void techEListInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		Tech techQuery = new Tech();
		techQuery.setDutyCode(dutyCode);
		List<Tech> techList = crewMapper.listCrewTech(techQuery);
		this.techMatch(techList, TechConstant.INEX_E, crewList);
	}

	/**
	 * 机组 排班授权初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void techZListInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		Tech techQuery = new Tech();
		techQuery.setDutyCode(dutyCode);
		List<Tech> techList = crewMapper.listCrewTech(techQuery);
		this.techMatch(techList, TechConstant.INEX_Z, crewList);
	}

	private void techMatch(List<Tech> techList, String inEx, List<Crew> crewList) {
		for (Crew c : crewList) {
			for (Tech t : techList) {
				if (StringUtils.equals(t.getWorkcode(), c.getWorkcode()) && StringUtils.equals(inEx, t.getInEx())) {
					if (StringUtils.equals(inEx, TechConstant.INEX_I)) {
						c.getTechIList().add(t);
					} else if (StringUtils.equals(inEx, TechConstant.INEX_E)) {
						c.getTechEList().add(t);
					} else if (StringUtils.equals(inEx, TechConstant.INEX_Z)) {
						c.getTechZList().add(t);
					} else {
						log.error("机组人员技术授权，有未识别的授权类型： " + t);
					}

				}
			}
		}
	}

	/**
	 * 机组技术资质初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void skillInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		// 查询所有的技术资质能力，并组装到crewList中
		List<Skill> skillList = crewMapper.listCrewSkill(dutyCode, null);
		for (Crew c : crewList) {
			for (Skill s : skillList) {
				if (StringUtils.equals(c.getWorkcode(), s.getWorkcode())) {
					c.setSkill(s);

					List<String> specialAirportList = StringToListUtil.getListDefault(s.getSpecialAirports());
					s.setSpecialAirportList(specialAirportList);
				}
			}
		}
	}

	/**
	 * 机组经历信息构造初始化，不包含经历内容数据，只是构造初始数据结构
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void crewFlightExperienceInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate,
			Date endFlightDate) {
		for (Crew c : crewList) {
			CrewFlightExperience cfe = new CrewFlightExperience();
			cfe.setWorkcode(c.getWorkcode());
			cfe.setBeforeFlightDate(beforeFlightDate);
			cfe.setEndFlightDate(endFlightDate);
			c.setCrewFlightExperience(cfe);
		}
	}

	/**
	 * 机组最后一次机场初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void lastAirportInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		// 一次性查询所有的最后一次机场
		Map<String, String> lastAirportMap = crewFlightExperienceService.listCrewLastAirport(dutyCode,
				beforeFlightDate);
		this.crewFlightExperienceFieldValueInit(lastAirportMap, crewList, "lastAirport");

	}

	/**
	 * 月飞最大限制，手动维护控制的限制 暂时按照机组排班授权限制，取最大值
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void flightDurationLimitOfMonthInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		for (Crew c : crewList) {
			Integer flightDurationLimitOfMonthMax = Integer.MIN_VALUE;
			;
			for (Tech t : c.getTechZList()) {
				if (t.getLimitOfMonth() != null && t.getLimitOfMonth() > flightDurationLimitOfMonthMax) {
					flightDurationLimitOfMonthMax = t.getLimitOfMonth();
				}
			}

			if (flightDurationLimitOfMonthMax > 0) {
				c.setFlightDurationLimitOfMonth(flightDurationLimitOfMonthMax);
			} else {
				c.setFlightDurationLimitOfMonth(RuleConstant.MAX_LIMIT_HOURS);
			}
		}

	}

	/**
	 * 机组近一年飞行时间初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void flightDurationLastYearInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeYear = crewFlightExperienceService.getFlightDateRangeYear(beforeFlightDate); // 近一年
		Map<String, Integer> flightDurationLastYearMap = crewFlightExperienceService.listFlightDurationSum(dutyCode,
				dateTimeRangeYear);
		this.crewFlightExperienceFieldValueInit(flightDurationLastYearMap, crewList, "flightDurationLastYear");
	}

	/**
	 * 机组近一月飞行时间初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void flightDurationLastMonthInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeMonth = crewFlightExperienceService.getFlightDateRangeMonth(beforeFlightDate); // 近一个月
		Map<String, Integer> flightDurationLastMonthMap = crewFlightExperienceService.listFlightDurationSum(dutyCode,
				dateTimeRangeMonth);
		this.crewFlightExperienceFieldValueInit(flightDurationLastMonthMap, crewList, "flightDurationLastMonth");
	}

	/**
	 * 机组近一年执勤期初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void dutyDurationLastYearInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeYear = crewFlightExperienceService.getFlightDateRangeYear(beforeFlightDate); // 近一年
		Map<String, Integer> dutyDurationLastYearMap = crewFlightExperienceService.listflightDutyDuration(dutyCode,
				dateTimeRangeYear);
		this.crewFlightExperienceFieldValueInit(dutyDurationLastYearMap, crewList, "dutyDurationLastYear");
	}

	/**
	 * 机组近一个月执勤期初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void dutyDurationLastMonthInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeMonth = crewFlightExperienceService.getFlightDateRangeMonth(beforeFlightDate); // 近一个月
		Map<String, Integer> dutyDurationLastMonthMap = crewFlightExperienceService.listflightDutyDuration(dutyCode,
				dateTimeRangeMonth);
		this.crewFlightExperienceFieldValueInit(dutyDurationLastMonthMap, crewList, "dutyDurationLastMonth");
	}

	/**
	 * 机组近一周执勤期初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void dutyDurationLastWeekInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeWeek = new DateTimeRange(new DateTime(beforeFlightDate).minusDays(6),
				new DateTime(beforeFlightDate).minusDays(1));
		Map<String, Integer> dutyDurationLastWeekMap = crewFlightExperienceService.listflightDutyDuration(dutyCode,
				dateTimeWeek);
		this.crewFlightExperienceFieldValueInit(dutyDurationLastWeekMap, crewList, "dutyDurationLastWeek");
	}

	/**
	 * 机组近一年过夜次数初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void nightPassCountLastYearInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeYear = crewFlightExperienceService.getFlightDateRangeYear(beforeFlightDate); // 近一年
		Map<String, Integer> nightPassCountLastYearMap = crewFlightExperienceService.listNightPassCount(dutyCode,
				dateTimeRangeYear);
		this.crewFlightExperienceFieldValueInit(nightPassCountLastYearMap, crewList, "nightPassCountLastYear");
	}

	/**
	 * 机组近一月过夜次数初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void nightPassCountLastMonthInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeYear = crewFlightExperienceService.getFlightDateRangeMonth(beforeFlightDate); // 近一月
		Map<String, Integer> nightPassCountLastYearMap = crewFlightExperienceService.listNightPassCount(dutyCode,
				dateTimeRangeYear);
		this.crewFlightExperienceFieldValueInit(nightPassCountLastYearMap, crewList, "nightPassCountLastMonth");
	}

	/**
	 * 机组近一年航段数量超过3次初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void flightMoreThanCountLastYearInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeYear = crewFlightExperienceService.getFlightDateRangeYear(beforeFlightDate); // 近一年
		Map<String, Integer> flightMoreThanFourCountLastYearMap = crewFlightExperienceService
				.listFlightMoreThanCount(dutyCode, dateTimeRangeYear);
		this.crewFlightExperienceFieldValueInit(flightMoreThanFourCountLastYearMap, crewList,
				"flightMoreThanCountLastYear");
	}

	/**
	 * 机组近一月航段数量超过3次初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void flightMoreThanCountLastMonthInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeYear = crewFlightExperienceService.getFlightDateRangeMonth(beforeFlightDate); // 近一月
		Map<String, Integer> flightMoreThanFourCountLastYearMap = crewFlightExperienceService
				.listFlightMoreThanCount(dutyCode, dateTimeRangeYear);
		this.crewFlightExperienceFieldValueInit(flightMoreThanFourCountLastYearMap, crewList,
				"flightMoreThanCountLastMonth");
	}

	/**
	 * 机组排版前某几天的执勤期计算
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void dutyDurationListInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		crewFlightExperienceService.initDutyDurationBeforeDay(dutyCode, crewList,
				new DateTime(beforeFlightDate).minusDays(6), new DateTime(beforeFlightDate));
	}

	/**
	 * 机型经历初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void cfeAcTypeListInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate, Date endFlightDate) {
		// 查询所有按机型的经历指标
		List<CrewFlightExperienceAcType> CrewFlightExperienceAcTypeList = crewFlightExperienceAcTypeService
				.crewFlightExperienceAcTypeListInit(dutyCode, beforeFlightDate, endFlightDate);
		for (Crew c : crewList) {
			CrewFlightExperience cfe = c.getCrewFlightExperience();
			for (CrewFlightExperienceAcType cfeAcType : CrewFlightExperienceAcTypeList) {
				if (StringUtils.equals(cfe.getWorkcode(), cfeAcType.getWorkcode())) {
					cfe.getCfeAcTypeList().add(cfeAcType);
				}
			}
		}
	}

	// 144小时内的休息期
	private void crewRestDateTimeListInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		// DateTime end = new
		// DateTime(beforeFlightDate).minusDays(1).millisOfDay().withMaximumValue();
		DateTime end = new DateTime(beforeFlightDate).withTimeAtStartOfDay();
		DateTime start = end.minusHours(RuleConstant.REST_FLIGHT_BEFORE_144);
		DateTimeRange dateTimeRange = new DateTimeRange(start, end);
		List<CrewRestDateTime> crewRestList = crewRestDateTimeService.listCrewRestDateTime(dateTimeRange, crewList,
				dutyCode, null);
		for (Crew c : crewList) {
			for (CrewRestDateTime crdt : crewRestList) {
				if (StringUtils.equals(c.getWorkcode(), crdt.getWorkcode())) {
					c.getCrewFlightExperience().getCrewRestDateTimeList().add(crdt);
				}
			}
		}
	}

	/**
	 * 私有方法，利用反射机制，给CrewFlightExperience属性赋值
	 * 
	 * @param fieldValueMap
	 * @param crewList
	 * @param fieldName
	 */
	private void crewFlightExperienceFieldValueInit(Map<String, ?> fieldValueMap, List<Crew> crewList,
			String fieldName) {
		for (Crew c : crewList) {
			CrewFlightExperience cfe = c.getCrewFlightExperience();
			for (Map.Entry<String, ?> entry : fieldValueMap.entrySet()) {
				if (StringUtils.equals(c.getWorkcode(), entry.getKey())) {
					try {
						BeanFiledUtils.forceSetFieldValue(cfe, fieldName, entry.getValue());
					} catch (Exception e) { 
						log.error("飞行员飞行经历属性赋值失败！，属性：" + fieldName +"不存在",e);
					}
				}
			}
		}
	}

	/**
	 * 查询起飞前，有48X休息期的次数
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	// private void crewRest48xCount(List<Crew> crewList, String dutyCode, Date
	// beforeFlightDate) {
	// for (Crew c : crewList) {
	// CrewFlightExperience cfe = c.getCrewFlightExperience();
	// int crewRest48xCount = 0;
	// for(CrewRestDateTime crdt : cfe.getCrewRestDateTimeList()){
	// if(crdt.getRestDateTimeRange().getDuration() >=
	// (RuleConstant.REST_48+RuleConstant.REST_X)*60){
	// crewRest48xCount ++;
	// }
	// }
	// cfe.setCrewRest48xCount(crewRest48xCount);
	// }
	//
	// }
	/**
	 * 查询起飞前有10X的休息期的次数
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */

	// private void crewRest10xCount(List<Crew> crewList, String dutyCode, Date
	// beforeFlightDate) {
	// for (Crew c : crewList) {
	// CrewFlightExperience cfe = c.getCrewFlightExperience();
	// int crewRest10xCount = 0;
	// List<CrewRestDateTime> crewRestDateTimeList = cfe.getCrewRestDateTimeList();
	// CrewRestDateTime lastCrewRestDateTime =
	// crewRestDateTimeList.get(crewRestDateTimeList.size()-1);
	// if(lastCrewRestDateTime.getRestDateTimeRange().getDuration() >=
	// (RuleConstant.REST_FLIGHT_BEFORE_10+RuleConstant.REST_X)*60){
	// crewRest10xCount = 1;
	// }
	//
	// cfe.setCrewRest10xCount(crewRest10xCount);
	// }
	// }
	/**
	 * 人员冲突列表
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void crewConflictOtherInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		List<CrewConflictOther> conflictOtherList = crewConflictService.listCrewConflictOther();
		for (Crew crew : crewList) {
			for (CrewConflictOther crewConflictOther : conflictOtherList) {
				if (StringUtils.equals(crew.getWorkcode(), crewConflictOther.getWorkcode())) {
					crew.setCrewConflictOther(crewConflictOther);
				}
			}
		}

	}

	/**
	 * 排班期间不在位信息列表
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 * @param endFlightDate
	 */
	private void crewTaskListBetweenFlightDateInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate,
			Date endFlightDate) {
		DateTimeRange dateTimeRange = new DateTimeRange(beforeFlightDate, endFlightDate);
		List<CrewTask> taskList = crewTaskService.listCrewTaskAll(dateTimeRange, dutyCode, null);
		for (Crew crew : crewList) {
			CrewFlightExperience cfe = crew.getCrewFlightExperience();
			for (CrewTask crewTask : taskList) {
				if (StringUtils.equals(crew.getWorkcode(), crewTask.getWorkcode())) {
					cfe.getCrewTaskListBetweenFlightDate().add(crewTask);
				}
			}
		}

	}

	/**
	 * 排版前机组成员的训练、检查有效期信息
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void crewExamineListInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		List<CrewExamine> crewExamineList = crewExamineService.listCrewExamineALL(null);
		for (Crew crew : crewList) {
			for (CrewExamine crewExamine : crewExamineList) {
				if (StringUtils.equals(crew.getWorkcode(), crewExamine.getWorkcode())) {
					crew.getCrewFlightExperience().getCrewExamineList().add(crewExamine);
				}
			}
		}
	}

	/**
	 * 排班前最后一次所飞连线信息
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void lastLinkLine(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		Map<String, LinkLine> map = this.crewFlightExperienceService.ListLastLinkLine(dutyCode, beforeFlightDate);
		this.crewFlightExperienceFieldValueInit(map, crewList, "lastLinkLine");
	}

	@Override
	public List<CrewInfoForAssign> listCrewInfoForAssignSimple(String dutyCode, Date beforeFlightDate) {
		// 基本信息查询
		List<Crew> crewList = this.listCrewBase(dutyCode);
		// 各种指标初始化开始
		this.techZListInit(crewList, dutyCode, beforeFlightDate);
		List<CrewInfoForAssign> caList = new ArrayList<>();
		for (Crew c : crewList) {
			CrewInfoForAssign ca = new CrewInfoForAssign();
			ca.setFlightDate(beforeFlightDate);
			BeanUtils.copyProperties(c, ca);

			String techZName = this.getTechZName(c.getTechZList());
			ca.setTechZName(techZName);
			caList.add(ca);
		}

		return caList;
	}

	@Override
	public List<CrewInfoForAssign> listCrewInfoForAssign(String dutyCode, Date beforeFlightDate) {
		DateTime endFlightDateTime = new DateTime(beforeFlightDate).millisOfDay().withMaximumValue();
		// 基本信息查询
		List<Crew> crewList = this.listCrewBase(dutyCode);

		// 各种指标初始化开始
		this.techZListInit(crewList, dutyCode, beforeFlightDate);
		this.skillInit(crewList, dutyCode, beforeFlightDate);
		this.crewFlightExperienceInit(crewList, dutyCode, beforeFlightDate, endFlightDateTime.toDate());
		this.lastAirportInit(crewList, dutyCode, beforeFlightDate);

		// 由于飞行时间和执勤期要加上今天的，所以用endFlightDateTime
		this.flightDurationLastYearInit(crewList, dutyCode, endFlightDateTime.toDate());
		this.flightDurationLastMonthInit(crewList, dutyCode, endFlightDateTime.toDate());
		this.dutyDurationLastMonthInit(crewList, dutyCode, endFlightDateTime.toDate());
		this.dutyDurationLastWeekInit(crewList, dutyCode, endFlightDateTime.toDate());

		List<Airport> airPortList = airPortMapper.listAllAirport();
		List<CrewInfoForAssign> caList = new ArrayList<>();
		for (Crew c : crewList) {
			CrewInfoForAssign ca = new CrewInfoForAssign();
			ca.setFlightDate(beforeFlightDate);
			BeanUtils.copyProperties(c, ca);

			String techZName = this.getTechZName(c.getTechZList());
			ca.setTechZName(techZName);

			ca.setFlightDurationLastYear(c.getCrewFlightExperience().getFlightDurationLastYear());
			ca.setFlightDurationLastMonth(c.getCrewFlightExperience().getFlightDurationLastMonth());
			ca.setDutyDurationLastMonth(c.getCrewFlightExperience().getDutyDurationLastMonth());
			ca.setDutyDurationLastWeek(c.getCrewFlightExperience().getDutyDurationLastWeek());
			// 获取最后一次落地机场
			String lastCityName = this.getAirportCityAbby(c.getCrewFlightExperience().getLastAirport(), airPortList);
			ca.setLastCityName(lastCityName);
			caList.add(ca);
		}

		return caList;
	}

	public String getAirportCityAbby(String airport4Code, List<Airport> airPortList) {
		for (Airport a : airPortList) {
			if (StringUtils.equals(a.getAirport4Code(), airport4Code)) {
				return a.getCityAbby();
			}
		}
		return null;
	}

	private String getTechZName(List<Tech> techZList) {
		String techZName = "";

		Set<String> techNameSet = new HashSet<>();
		for (Tech t : techZList) {
			techNameSet.add(t.getTechName());
		}
		int techNameSetSize = techNameSet.size();
		if (techNameSetSize == 1) {
			techZName = techZList.get(0).getTechName();
		} else {

			for (Tech t : techZList) {
				techNameSet.add(t.getTechName());
				techZName += t.getAcType() + t.getTechName();
			}
		}

		return techZName;
	}

	@Override
	public Crew getCrewByWorkcode(String workcode) {
		return crewMapper.getCrewByWorkcode(workcode);
	}

	/**
	 * 近一年夜航次数指标
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void nightFlyCountLastYearInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeYear = crewFlightExperienceService.getFlightDateRangeYear(beforeFlightDate); // 近一年
		Map<String, Integer> nightFlyCountLastMap = crewFlightExperienceService.nightFlyCount(dutyCode,
				dateTimeRangeYear);
		this.crewFlightExperienceFieldValueInit(nightFlyCountLastMap, crewList, "nightFlyCountLastYear");

	}

	/**
	 * 近一月夜航次数指标
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void nightFlyCountLastMonthInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRangeYear = crewFlightExperienceService.getFlightDateRangeMonth(beforeFlightDate); // 近一月
		Map<String, Integer> nightFlyCountLastMap = crewFlightExperienceService.nightFlyCount(dutyCode,
				dateTimeRangeYear);
		this.crewFlightExperienceFieldValueInit(nightFlyCountLastMap, crewList, "nightFlyCountLastMonth");

	}

	/**
	 * 最后一次休假或停飞，距离beforeFlightDate的天数，如果没有，则距离天数为 Integer.max
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void lastVacationAndStopFlyInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTime beforeFlightDateTime = new DateTime(beforeFlightDate);
		Map<String, Integer> map = new HashMap<>();
		List<CrewTask> taskList = crewTaskMapper.listCrewTaskForLastVacationAndStopFly(dutyCode, null,
				beforeFlightDate);
		for (Crew crew : crewList) {
			String workcode = crew.getWorkcode();
			DateTime startDateTime = new DateTime(2000, 1, 1, 0, 0);
			for (CrewTask ct : taskList) {
				if (StringUtils.equals(workcode, ct.getWorkcode())) {
					startDateTime = new DateTime(ct.getEnd());
				}
			}

			Duration duration = new Duration(startDateTime, beforeFlightDateTime);
			int dayDiff = (int) duration.getStandardDays();
			map.put(workcode, dayDiff);
		}

		this.crewFlightExperienceFieldValueInit(map, crewList, "lastVacationAndStopFly");
	}

	/**
	 * 近一个月差航线次数初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void badFlightCountLastMonthInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRange = crewFlightExperienceService.getFlightDateRangeMonth(beforeFlightDate); // 近一月
		Map<String, Integer> map = crewFlightExperienceService.badFlightCount(dutyCode, dateTimeRange);
		this.crewFlightExperienceFieldValueInit(map, crewList, "badFlightCountLastMonth");
	}

	/**
	 * 近一年差航线次数初始化
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void badFlightCountLastYearInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTimeRange dateTimeRange = crewFlightExperienceService.getFlightDateRangeYear(beforeFlightDate); // 近一月
		Map<String, Integer> map = crewFlightExperienceService.badFlightCount(dutyCode, dateTimeRange);
		this.crewFlightExperienceFieldValueInit(map, crewList, "badFlightCountLastYear");
	}

	/**
	 * 初始化近6个月航班机场集合
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void airPortsSetLastSixMonthInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTime end = new DateTime(beforeFlightDate).minus(1).millisOfDay().withMaximumValue();
		DateTime start = end.minusMonths(6);
		DateTimeRange dateTimeRange = new DateTimeRange(start.toDate(), end.toDate());
		for (Crew crew : crewList) {
			Set<String> set = new HashSet<>();
			List<FlightInfo> fListAll = crew.getCrewFlightExperience().getFlightInfoListYear();
			List<FlightInfo> fList = crewFlightExperienceService.getFlightInfoListByCrewAndDateTimeRange(fListAll,
					dateTimeRange);
			for (FlightInfo f : fList) {
				set.add(f.getDepartureAirport() + "-" + f.getArrivalAirport());
			}
			crew.getCrewFlightExperience().setAirPortsSetLastSixMonth(set);
		}
	}

	/**
	 * 所有机型的所有经历时间
	 * 
	 * @param crewList
	 * @param dutyCode
	 * @param beforeFlightDate
	 */
	private void seatDurationAllInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		for (Crew crew : crewList) {
			List<CrewFlightExperienceAcType> cfeaList = crew.getCrewFlightExperience().getCfeAcTypeList();
			int seatDurationCount = 0;
			for (CrewFlightExperienceAcType cfea : cfeaList) {
				int seatDuration = cfea.getSeatDuration();
				seatDurationCount = +seatDuration;
			}
			crew.getCrewFlightExperience().setSeatDurationAll(seatDurationCount);
		}
	}

	private void lastSickLeaveInit(List<Crew> crewList, String dutyCode, Date beforeFlightDate) {
		DateTime beforeFlightDateTime = new DateTime(beforeFlightDate);
		Map<String, Integer> map = new HashMap<>();
		List<CrewTask> taskList = crewTaskMapper.listCrewTaskForLastSickLeave(dutyCode, null, beforeFlightDate);
		for (Crew crew : crewList) {
			String workcode = crew.getWorkcode();
			DateTime startDateTime = new DateTime(2000, 1, 1, 0, 0);
			for (CrewTask ct : taskList) {
				if (StringUtils.equals(workcode, ct.getWorkcode())) {
					startDateTime = new DateTime(ct.getEnd());
				}
			}

			Duration duration = new Duration(startDateTime, beforeFlightDateTime);
			int dayDiff = (int) duration.getStandardDays();
			map.put(workcode, dayDiff);
		}

		this.crewFlightExperienceFieldValueInit(map, crewList, "lastSickLeave");
	}

	@Override
	public List<Crew> listCrewInfoForVo(String dutyCode, String workcode) {
		// 基本信息查询
		List<Crew> crewList = this.listCrewBase(dutyCode, workcode);
		this.techZListInit(crewList, dutyCode, null);
		return crewList;
	}

	@Override
	public List<Crew> listCrewAllInfoForRuleCheck(String dutyCode, List<String> workcodeList, Date flightDate) {
		// 基本信息查询
		List<Crew> crewListAll = this.listCrewBase(dutyCode);

		List<Crew> crewList = new ArrayList<>();
		if (CollectionUtils.isEmpty(workcodeList)) {
			crewList = crewListAll;
		} else {
			for (String workcode : workcodeList) {
				for (Crew crew : crewListAll) {
					if (StringUtils.equals(workcode, crew.getWorkcode())) {
						crewList.add(crew);
					}
				}

			}
		}

		// 各种指标初始化开始

		this.techZListInit(crewList, dutyCode, flightDate);
		return crewList;
	}

	@Override
	public Page listCrewInfoForVoPage(String moduleFlag, String workcode, Page page) {
		PageHelper.startPage(page.getPageNumber(), page.getPageSize());
		List<Crew> crewList = crewMapper.listCrewBase(moduleFlag, workcode);
		// 计算年龄
		for (Crew c : crewList) {
			Date birthday = c.getBirthday();
			int age = AgeUtil.getAgeFromBirthTime(birthday);
			c.setAge(age);
		}
		this.techZListInit(crewList, moduleFlag, null);

		PageInfo<Crew> pageInfo = new PageInfo<Crew>(crewList);
		page.setTotal(String.valueOf(pageInfo.getTotal()));
		page.setRows(pageInfo.getList());

		return page;
	}

}
